﻿#pragma once

#include "usk/uskcore_export.h"

#include "cppmicroservices/Bundle.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/em/Event.hpp"
#include "cppmicroservices/logservice/LogService.hpp"
#include "fmt/format.h"

#include <memory>

namespace usk {
    namespace core {
        class OsgiPrivate;
        class USKEventAdminImpl;

        class USK_USKCore_API OSGI {
        public:
            static OSGI &GetInstance();

            /// @brief 初始化
            bool Init();

            /// @brief 反初始化
            void UnInit();

            /// @brief 添加需要安装的bundle文件的路径
            /// @param path 文件路径(可以是目录)
            bool AddBundleInstallPath(const char *path);

            /// @brief 安装已经添加的bundle文件
            void InstallBundles();

            /// @brief 使用Post方式发送事件(异步，不保证顺序)
            void PostEvent(cppmicroservices::service::em::Event const &evt);

            /// @brief 使用Send方式发送事件(阻塞当前调用线程)
            void SendEvent(cppmicroservices::service::em::Event const &evt);

            /// @brief 获取所有已经安装的bundle
            std::vector<cppmicroservices::Bundle> GetBundles();

            /// @brief 获取OSGI框架的BundleContext
            cppmicroservices::BundleContext GetBundleContext();

            /// @brief 获取日志服务
            std::shared_ptr<cppmicroservices::logservice::LogService> GetLogService();

        protected:
            friend class USKEventAdminImpl;
            explicit OSGI();

            void OnEvent(const void *pSender, cppmicroservices::service::em::Event &ev);

            std::shared_ptr<OsgiPrivate> d_;
        };

        template<typename... Args>
        void LogMessage(cppmicroservices::logservice::SeverityLevel level, fmt::format_string<Args...> fmt,
                        Args &&...args) {
            OSGI &core = OSGI::GetInstance();
            const auto log_service = core.GetLogService();
            if (nullptr == log_service) {
                return;
            }
            const std::string message = fmt::format(fmt, std::forward<Args>(args)...);
            log_service->Log(level, message);
        }
    } // namespace core
} // namespace usk

#define LOG_DEBUG(...) usk::core::LogMessage(cppmicroservices::logservice::SeverityLevel::LOG_DEBUG, __VA_ARGS__)
#define LOG_INFO(...) usk::core::LogMessage(cppmicroservices::logservice::SeverityLevel::LOG_INFO, __VA_ARGS__)
#define LOG_WARN(...) usk::core::LogMessage(cppmicroservices::logservice::SeverityLevel::LOG_WARN, __VA_ARGS__)
#define LOG_ERROR(...) usk::core::LogMessage(cppmicroservices::logservice::SeverityLevel::LOG_ERROR, __VA_ARGS__)
